iT邦幫忙

2024 iThome 鐵人賽

DAY 13
0

不同於上一篇的 Sanity 圖片 url 直接在查詢圖片時就把圖片 url 查詢出來或是用 _ref 組合出圖片的 url。
這次要使用的是 @Sanity/image-url 這套官方的圖片套件。


@Sanity/image-url 基本使用

要使用 @Sanity/image-url 不難,首先 npm 引入套件:

npm install @sanity/image-url --save

並且 import 套件再傳入 Saniry 連線的 client 物件:

import { createClient } from "next-sanity";
import { dataset, projectId } from "../env";
// 引入套件
import imageUrlBuilder from "@sanity/image-url";
import type { SanityImageSource } from "@sanity/image-url/lib/types/types";

// Sanity 連線 client 物件
export const client = createClient({
  projectId,
  dataset,
  useCdn: true,
});

export function urlFor(source: SanityImageSource) {
	// 傳入 client 物件作為連線資訊後
  return imageUrlBuilder(client)
	  .image(source); // <- 再傳入 Sanity 的圖片資源物件
}

接下來要使用 Sanity 圖片的地方只要使用 export 出來的 urlFor 就可以了。

import { client, urlFor } from "@/app/sanity/lib/client";

export default async function ImageTest() {
	// 取得文章物件
	const post = await client.fetch(BLOG_POSTS_BY_SLUG_QUERY_TEST, {
    slug: "圖解-java-zip-包裹檔案",
  });
  
  // ...
  
  // 圖片 url
	console.log(urlFor(post.heroImage).url());

  return (
	  // ...
  );
}

只要將圖片物件傳進去 urlFor ,並呼叫 url() 方法就可以了。


圖片設定

@Sanity/image-url 不只可以作為呼叫圖片 url 的方法,它還提供了圖片寬高、blur、rect、quality 等等的屬性設定方法。

// {imageUrl}.jpg
urlFor(post.heroImage).url()

// {imageUrl}.jpg?w=200
urlFor(post.heroImage).width(200).url()

// {imageUrl}.jpg?rect=100,50,215,200
urlFor(post.heroImage).rect(100, 50, 215, 200).url()

// {imageUrl}.jpg?q=100
urlFor(post.heroImage).quality(100).url()

// {imageUrl}.jpg?h=300&q=20
urlFor(post.heroImage).height(300).quality(20).url()

Next.js 與 @Sanity/image-url 的 RWD 圖片 Component

next/image Component 中,有一個 prop 是 loader,他接受一個 callback 方法並且回 width, src, quality 屬性。
分別傳入一些圖片 Image 載入時的的狀態值,對於載入時渲染圖片是很有幫助的。

這邊單獨為 Sanity 建立一個圖片顯示的 Component,叫做 SanityImage.tsx

// app/components/SanityImage.tsx

"use client";

import { urlFor } from "@/app/sanity/lib/client";
import Image, { type ImageProps } from "next/image";
import type { SanityImageSource } from "@sanity/image-url/lib/types/types";

// 將 next/image 中的 ImageProps 提取出來,並將 src 屬性移除
// 並且加入 source 屬性,這樣就可以將 Sanity 的圖片資料傳入
type Props = Omit<ImageProps, "src"> & {
  source: SanityImageSource;
};

export default function SanityImage({ source, alt, ...props }: Props) {
  return (
    <Image
      {...props}
      src="image src doesn't matter in this case"
      alt={alt}
      loader={({ width, quality = 100 }) =>
        // 根據傳入的 source 取得圖片的 URL
        // 並且指定寬度和品質,達到最佳的圖片效果
        urlFor(source).width(width).quality(quality).url()
      }
    />
  );
}

接下來可以引入到我們原本的 app/[slug]/page.tsx Component 中了:

// ...
import SanityImage from "@/app/components/SanityImage";

export default async function Post({ params }: { params: { slug: string } }) {
  // ...

  return (
    <div className="post">
	    {/* ... */}
      <div className="relative w-full max-w-[770px] aspect-[770/480]">
        <SanityImage
          source={post.heroImage}
          alt={`${post.title} banner image`}
          fill
          sizes="(max-width: 770px) 50vw, 770px"
        />
      </div>
      {/* ... */}
    </div>
  );
}

這樣就會有個可顯示 Sanity 圖片並且具備基礎 RWD 效果的 Component 了!


上一篇
Day 12 - Sanity 圖片 url 參數解析
下一篇
Day 14 - Sanity Markdown Plugin
系列文
用 Sanity 跟 Nextjs 重寫個人部落格30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言